package com.zhu.java8;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;


/**
 * Created with IntelliJ IDEA.
 *
 * @Author: zhujiabao
 * @Date: 2022/04/19/14:52
 * @Description:使用 Stream 简化集合操作
 */
public class CoolStreamTest {

    /*我们看一个具体的例子。这里有一段 20 行左右的代码，实现了如下的逻辑：

    把整数列表转换为 Point2D 列表；

    遍历 Point2D 列表过滤出 Y 轴 >1 的对象；

    计算 Point2D 点到原点的距离；

    累加所有计算出的距离，并计算距离的平均值。
    * */


    public static void main(String[] args) {
        List<Integer> ints = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            ints.add(i);
        }

        System.out.println(ints);
        System.out.println("--------calc(ints)--------");
        double average = calc(ints);
        System.out.println(average);
        System.out.println("--------calcCool(ints)--------");
        double streamResult = calcCool(ints);
        System.out.println(average);

        System.out.println("--------calcCool(ints)--------");
        System.out.println();

        //测试方法，如果 average 等于 streamResult 则不报错
        assertThat(average, is(streamResult));
    }

    /*普通方法，计算距离和平均值*/
    private static double calc(List<Integer> ints) {

        //临时中间集合
        List<Point2D> point2DList = new ArrayList<>();
        for (Integer i : ints) {
            point2DList.add(new Point2D.Double((double) i % 3, (double) i % 3));
        }

        //临时变量，纯粹是为了获得最后结果需要的中间变量。
        double total = 0;
        int count = 0;
        for (Point2D point2D : point2DList) {
            //过滤
            if (point2D.getY() > 1) {
                //算距离
                double distance = point2D.distance(0, 0);
                total += distance;
                count++;
            }
        }

        return count >= 0 ? total / count : 0;

    }

    /*java8 Stream写法，计算距离和平均值*/
    private static double calcCool(List<Integer> ints) {
        return ints.stream().map(i -> new Point2D.Double((double) i % 3, (double) i % 3))
                .filter(point2D -> point2D.getY() > 1)
                .mapToDouble(point -> point.distance(0, 0))
                .average()
                .orElse(0);

    }




}
